package org.etherframework.tests.features.access
{
	import flash.system.ApplicationDomain;
	
	import mx.core.IVisualElement;
	
	import org.etherframework.core.IModule;
	import org.etherframework.tests.features.access.configs.LocalConfig;
	import org.etherframework.tests.features.access.dependencies.ChildModuleDependency;
	import org.etherframework.tests.features.access.dependencies.GlobalDependency;
	import org.etherframework.tests.features.access.dependencies.Module2Dependency;
	import org.etherframework.tests.features.access.dependencies.ModuleDependency;
	import org.etherframework.tests.features.access.dependencies.OverlapedDependency;
	import org.etherframework.tests.features.access.dependencies.TopModuleDependency;
	import org.etherframework.tests.utils.ModuleInfo;
	import org.etherframework.tests.utils.TestUtility;
	import org.fluint.uiImpersonation.UIImpersonator;
	import org.hamcrest.assertThat;
	import org.hamcrest.object.equalTo;
	import org.hamcrest.object.instanceOf;
	import org.hamcrest.object.notNullValue;
	import org.hamcrest.object.nullValue;
	
	import spark.components.Group;

	public class when_using_dependency_local_access
	{	
		private static var _testUtility:TestUtility = new TestUtility();
		private static var _globalView:Group;
		private static var _topModule:ModuleInfo;
		private static var _module:ModuleInfo;
		private static var _childModule:ModuleInfo;
		private static var _module2:ModuleInfo;
		private static var _globalModule:ModuleInfo;
		
		[BeforeClass]
		public static function setUpBeforeClass():void
		{
			const appDomain:ApplicationDomain = ApplicationDomain.currentDomain;
			_topModule = _testUtility.createModuleInfo(new LocalConfig(), null, null, null, appDomain);
			_module = _testUtility.createModuleInfo(new LocalConfig(), null, null, null, appDomain);
			_childModule = _testUtility.createModuleInfo(new LocalConfig(), null, null, null, appDomain);
			_module2 = _testUtility.createModuleInfo(new LocalConfig(), null, null, null, appDomain);
			_globalModule = _testUtility.createModuleInfo(new LocalConfig(), null, null, null, appDomain);
			_globalView = UIImpersonator.addChild(new Group()) as Group;
			
			// Module hierarchical structure is view dependent. So as to resolve ancestor
			// module you need to address some ancestor view which hosts other module.
			_globalView.addElement(_topModule.module.view as IVisualElement);
			Group(_topModule.module.view).addElement(_module.module.view as IVisualElement);
			Group(_topModule.module.view).addElement(_module2.module.view as IVisualElement);
			Group(_module.module.view).addElement(_childModule.module.view as IVisualElement);
			
			_topModule.module.dependencies.addClass(TopModuleDependency);
			_topModule.module.dependencies.addSingleton(OverlapedDependency);
			_module.module.dependencies.addClass(ModuleDependency);
			_module.module.dependencies.addSingleton(OverlapedDependency);
			_module2.module.dependencies.addClass(Module2Dependency);
			_childModule.module.dependencies.addClass(ChildModuleDependency);
			_globalModule.module.dependencies.addClass(GlobalDependency);
		}
		
		[AfterClass]
		public static function tearDownAfterClass():void
		{
			_testUtility.dispose();
		}
		
		[Test(order=1)]
		public function when_getting_top_dependency_it_should_be_resolved():void
		{
			var error:Error;
			assertThat(_topModule.module.ether.dependencies.getInstance(TopModuleDependency), instanceOf(TopModuleDependency));
			
			try {
				_topModule.module.ether.dependencies.getInstance(GlobalDependency);
			} catch (e:Error) {error = e;}
			assertThat(error, notNullValue());
			error = null;
			
			try {
				_module.module.ether.dependencies.getInstance(TopModuleDependency);
			} catch (e:Error) {error = e;}
			assertThat(error, notNullValue());
			error = null;
			
			try {
				_childModule.module.ether.dependencies.getInstance(TopModuleDependency);
			} catch (e:Error) {error = e;}
			assertThat(error, notNullValue());
		}
		
		[Test(order=2)]
		public function when_getting_module_dependency_it_should_be_resolved():void
		{
			var error:Error;
			assertThat(_module.module.ether.dependencies.getInstance(ModuleDependency), instanceOf(ModuleDependency));
			
			try {
				_module.module.ether.dependencies.getInstance(GlobalDependency);
			} catch (e:Error) {error = e;}
			assertThat(error, notNullValue());
			error = null;
			
			try {
				_topModule.module.ether.dependencies.getInstance(ModuleDependency);
			} catch (e:Error) {error = e;}
			assertThat(error, notNullValue());
			error = null;
			
			try {
				_childModule.module.ether.dependencies.getInstance(ModuleDependency);
			} catch (e:Error) {error = e;}
			assertThat(error, notNullValue());
		}
		
		[Test(order=3)]
		public function when_getting_child_dependency_it_should_be_resolved():void
		{
			var error:Error;
			assertThat(_childModule.module.ether.dependencies.getInstance(ChildModuleDependency), instanceOf(ChildModuleDependency));
			
			try {
				_childModule.module.ether.dependencies.getInstance(GlobalDependency);
			} catch (e:Error) {error = e;}
			assertThat(error, notNullValue());
			error = null;
			
			try {
				_topModule.module.ether.dependencies.getInstance(ChildModuleDependency);
			} catch (e:Error) {error = e;}
			assertThat(error, notNullValue());
			error = null;
			
			try {
				_module.module.ether.dependencies.getInstance(ChildModuleDependency);
			} catch (e:Error) {error = e;}
			assertThat(error, notNullValue());
		}
		
		[Test(order=5)]
		public function when_getting_dependencies_from_another_branch_it_should_be_resolved():void
		{
			var error:Error;
			assertThat(_module2.module.ether.dependencies.getInstance(Module2Dependency), instanceOf(Module2Dependency));
			
			try {
				_module2.module.ether.dependencies.getInstance(OverlapedDependency);
			} catch (e:Error) {error = e;}
			assertThat(error, notNullValue());
			error = null;
			
			try {
				_module2.module.ether.dependencies.getInstance(GlobalDependency);
			} catch (e:Error) {error = e;}
			assertThat(error, notNullValue());
			error = null;
			
			try {
				_module2.module.ether.dependencies.getInstance(ModuleDependency);
			} catch (e:Error) {error = e;}
			assertThat(error, notNullValue());
		}
	}
}